﻿using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using net.windward.api.csharp;
using net.windward.utils.ado;

namespace ArrowScheduleCore
{
    /// <summary>
    /// This is a single report that was run as a scheduled event.
    /// </summary>
    public class ScheduleRunItem
    {

        /// <summary>
        /// The error results from running a report.
        /// </summary>
        public enum RESULT
        {
            /// <summary>The report was successful.</summary>
            SUCCESS,
            /// <summary>There was a security violation (probably the login to a datasource).</summary>
            SECURITY_ERROR,
            /// <summary>The report engine threw an error.</summary>
            REPORT_ERROR,
            /// <summary>An unknown error occured.</summary>
            OTHER_ERROR
        };

        /// <summary>
        /// Returns a user firendly string for the error.
        /// </summary>
        /// <param name="result">The error.</param>
        /// <returns>The user firendly string.</returns>
        public static string DisplayResult(RESULT result)
        {
            switch (result)
            {
                case RESULT.SUCCESS:
                    return GlobalStrings.ScheduleRunItem_errorSuccess;
                case RESULT.REPORT_ERROR:
                    return GlobalStrings.ScheduleRunItem_errorReport;
            }

            return GlobalStrings.ScheduleRunItem_errorOther;
        }

        private long scheduleRunId;
        private readonly long scheduleId;
        private readonly DateTime runTime; // UTC
        private readonly RESULT runResult;
        private readonly string runMessage;
        private readonly string reportFilename;
        private readonly string reportEmailTo;

        /// <summary>
        /// Create the object of a scheduled report result.
        /// </summary>
        /// <param name="scheduleRunId">The primary key.</param>
        /// <param name="scheduleId">The PK of the event that ran this report.</param>
        /// <param name="runTime">When the report was run in UTC.</param>
        /// <param name="runResult">The result of running the report.</param>
        /// <param name="runMessage">The error message if there was an error.</param>
        /// <param name="reportFilename">The filename the report was saved as, can be null.</param>
        /// <param name="reportEmailTo">The addresses the report was emailed to, can be null.</param>
        public ScheduleRunItem(long scheduleRunId, long scheduleId, DateTime runTime, RESULT runResult, string runMessage, string reportFilename, string reportEmailTo)
        {
            this.scheduleRunId = scheduleRunId;
            this.scheduleId = scheduleId;
            this.runTime = runTime;
            this.runResult = runResult;
            this.runMessage = runMessage;
            this.reportFilename = reportFilename;
            this.reportEmailTo = reportEmailTo;
        }

        /// <summary>
        /// Create the object of a scheduled report result.
        /// </summary>
        /// <param name="scheduleId">The PK of the event that ran this report.</param>
        /// <param name="runTime">When the report was run in UTC.</param>
        /// <param name="runResult">The result of running the report.</param>
        /// <param name="runMessage">The error message if there was an error.</param>
        /// <param name="reportFilename">The filename the report was saved as, can be null.</param>
        /// <param name="reportEmailTo">The addresses the report was emailed to, can be null.</param>
        public ScheduleRunItem(long scheduleId, DateTime runTime, RESULT runResult, string runMessage, string reportFilename, string reportEmailTo)
        {
            scheduleRunId = WrConnectionParams.NULL_PK;
            this.scheduleId = scheduleId;
            this.runTime = runTime;
            this.runResult = runResult;
            this.runMessage = runMessage;
            this.reportFilename = reportFilename;
            this.reportEmailTo = reportEmailTo;
        }

        /// <summary>
        /// Create the object of a scheduled report result.
        /// </summary>
        /// <param name="item">The event object to build this from</param>
        public ScheduleRunItem(ScheduleItem item)
        {
            scheduleRunId = WrConnectionParams.NULL_PK;
            scheduleId = item.Id;
            runTime = item.RunLast;
            runResult = item.RunResult == null ? RESULT.SUCCESS : RESULT.REPORT_ERROR;
            runMessage = item.RunResult;
        }

        /// <summary>
        /// Create the object of a scheduled report result.
        /// </summary>
        /// <param name="item">The event object to build this from</param>
        /// <param name="reportFilename">The filename the report was saved as, can be null.</param>
        /// <param name="reportEmailTo">The addresses the report was emailed to, can be null.</param>
        public ScheduleRunItem(ScheduleItem item, string reportFilename, string reportEmailTo)
        {
            scheduleRunId = WrConnectionParams.NULL_PK;
            scheduleId = item.Id;
            runTime = item.RunLast;
            runResult = item.RunResult == null ? RESULT.SUCCESS : RESULT.REPORT_ERROR;
            runMessage = item.RunResult;
            this.reportFilename = reportFilename;
            this.reportEmailTo = reportEmailTo;
        }

        /// <summary>
        /// The primary key of this record.
        /// </summary>
        public long Id
        {
            get { return scheduleRunId; }
        }

        /// <summary>
        /// Sets the primary key. Should only be called when this has been inserted into a database.
        /// </summary>
        /// <param name="id">The primary key.</param>
        public void setId(long id)
        {
            scheduleRunId = id;
        }

        /// <summary>
        /// The schedule this run is for.
        /// </summary>
        public long ScheduleId
        {
            get { return scheduleId; }
        }

        /// <summary>
        /// Time the report was run in UTC.
        /// </summary>
        public DateTime RunTime
        {
            get { return runTime; }
        }

        /// <summary>
        /// The result code of this run.
        /// </summary>
        public RESULT RunResult
        {
            get { return runResult; }
        }

        /// <summary>
        /// The error message of this run. null if it ran successfully.
        /// </summary>
        public string RunMessage
        {
            get { return runMessage; }
        }

        /// <summary>
        /// The filename the report was saved as, can be null.
        /// </summary>
        public string ReportFilename
        {
            get { return reportFilename; }
        }

        public Report Report { get; set; }
        public Stream ReportStream { get; set; }

        /// <summary>
        /// The addresses the report was emailed to, can be null.
        /// </summary>
        public string ReportEmailTo
        {
            get { return reportEmailTo; }
        }

        /// <summary>
        /// true if there was an error generating this report.
        /// </summary>
        public bool IsError
        {
            get { return !string.IsNullOrEmpty(runMessage); }
        }
    }

    /// <summary>
    /// A collection of ScheduleRunItem objects.
    /// </summary>
    public class ScheduleRunItemCollection : Collection<ScheduleRunItem>
    {
        /// <summary>
        /// Return the run report with the requested primary key. Returns null if not found.
        /// </summary>
        /// <param name="id">The primary key to look for.</param>
        /// <returns>The requested report.</returns>
        public ScheduleRunItem FindById(long id)
        {
            return this.FirstOrDefault(item => item.Id == id);
        }
    }
}
